home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / relay / ihave_yes.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  6KB  |  218 lines

  1. /*
  2.  * Implement the Usenet ihave/sendme control messages,
  3.  * as per RFC 1036 (nee 850).
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #ifndef AMIGA
  9. #  include <sys/types.h>
  10. #endif /* AMIGA */
  11.  
  12. #include "libc.h"
  13. #include "news.h"
  14. #include "config.h"
  15. #include "headers.h"
  16. #include "article.h"
  17. #include "history.h"
  18. #include "fgetmfs.h"
  19. #include "msgs.h"
  20. #include "transmit.h"
  21.  
  22. #ifndef SENDMEDISTR
  23. /* kludge: distinguished distribution for sendmes */
  24. #define SENDMEDISTR "sendme"
  25. #endif
  26.  
  27. #ifndef IHAVEDISTR
  28. /* kludge: distinguished distribution for ihaves */
  29. #define IHAVEDISTR "ihave"
  30. #endif
  31.  
  32. #ifndef AVEARTSIZE
  33. #define AVEARTSIZE 3000
  34. #endif
  35.  
  36. #define PROTO_IHAVE 0
  37. #define PROTO_SENDME 1
  38.  
  39. /* static forwards */
  40. FORWARD void doproto(), procmsgids(), procbodymsgids();
  41. FORWARD statust faketrans();
  42.  
  43. /*
  44.  * Read message-IDs from args or control message body,
  45.  * look them up in history, post a sendme to to.remotesys (via the batcher
  46.  * to avoid deadlock) consisting of the message-IDs not in history.
  47.  * The "posting" consists of transmitting to a system matching
  48.  * "to.remotesys" in sys, which had better have the I flag on.
  49.  * ihave message-ID-list remotesys    generate a sendme from message-ID-list
  50.  */
  51. void
  52. ihave(args, art)
  53. char *args;
  54. struct article *art;
  55. {
  56.     doproto(args, art, IHAVEDISTR, PROTO_IHAVE);
  57. }
  58.  
  59. /*
  60.  * Read message-IDs from args or control message body,
  61.  * transmit the corresponding articles to a system matching
  62.  * "to.remotesys/sendme" in sys, which will typically name a batch file.
  63.  * sendme message-ID-list remotesys    send articles named to remotesys
  64.  */
  65. void
  66. sendme(args, art)
  67. char *args;
  68. struct article *art;
  69. {
  70.     doproto(args, art, SENDMEDISTR, PROTO_SENDME);
  71. }
  72.  
  73. static void
  74. doproto(args, art, distr, proto)
  75. char *args;
  76. register struct article *art;
  77. char *distr;
  78. int proto;
  79. {
  80.     register char *argscp = skipsp(args), *remotesys;
  81.  
  82.     if (*argscp == '\n' || *argscp == '\0')    /* no args */
  83.         return;
  84.  
  85.     argscp = strsave(argscp);
  86.  
  87.     /* dig out the remote system name */
  88.     remotesys = rindex(argscp, ' ');    
  89.     if (remotesys == NULL)            /* no msg-ids in command */
  90.         remotesys = argscp;
  91.     else {
  92.         remotesys = argscp + strlen(argscp) - 1;    /* last byte */
  93.         while (isascii(*remotesys) && isspace(*remotesys))
  94.             *remotesys-- = '\0';    /* back up to non-whitespace */
  95.         remotesys = rindex(argscp, ' ');
  96.         if (remotesys == NULL)        /* no msg-ids in command */
  97.             remotesys = argscp;
  98.         else
  99.             *remotesys++ = '\0';    /* separate msg-ids & sys name */
  100.     }
  101.     if (strcmp(remotesys, hostname()) != 0)    /* remotesys may not be me */
  102.         if (remotesys != argscp)    /* msg-ids in command */
  103.             procmsgids(art, argscp, remotesys, distr, proto);
  104.         else
  105.             procbodymsgids(art, remotesys, distr, proto);
  106.     free(argscp);
  107. }
  108.  
  109. /*
  110.  * Process a list of message-ids in msgidln: look them up
  111.  * and "transmit" the articles to to.remotesys.
  112.  */
  113. static void
  114. procmsgids(art, msgidln, remotesys, distr, proto)
  115. struct article *art;
  116. char *msgidln, *remotesys, *distr;
  117. int proto;
  118. {
  119.     char *cpmsgid = strsave(skipsp(msgidln));
  120.     register char *msgid = cpmsgid, *endmsgid;
  121.     register int save, sendit;
  122.  
  123.     for (; *msgid != '\n' && *msgid != '\0'; msgid = skipsp(endmsgid)) {
  124.         for (endmsgid = msgid; *endmsgid != '\0' &&
  125.             isascii(*endmsgid) && !isspace(*endmsgid); ++endmsgid)
  126.             ;            /* skip msgid */
  127.  
  128.         save = *endmsgid;
  129.         *endmsgid = '\0';        /* terminate msgid at whitespace */
  130.         if (proto == PROTO_IHAVE)
  131.             sendit = !alreadyseen(msgid);    /* sendme from remotesys */
  132.         else
  133.             sendit = alreadyseen(msgid);    /* sendme to remotesys */
  134.         if (sendit)
  135.             art->a_status |= faketrans(msgid, remotesys, distr, proto);
  136.         *endmsgid = save;
  137.     }
  138.     free(cpmsgid);
  139. }
  140.  
  141. static void
  142. procbodymsgids(art, remotesys, distr, proto)
  143. register struct article *art;
  144. char *remotesys, *distr; 
  145. int proto;
  146. {
  147.     register FILE *arttext;
  148.  
  149.     arttext = fopenwclex(art->a_tmpf, "r");
  150.     if (arttext != NULL) {
  151.         char *line;
  152.  
  153.         while ((line = fgetms(arttext)) != NULL && *line != '\n')
  154.             nnfree(&line);        /* skip header */
  155.         if (line != NULL) {        /* article body exists */
  156.             nnfree(&line);        /* toss blank separating line */
  157.             while ((line = fgetms(arttext)) != NULL) {
  158.                 procmsgids(art, line, remotesys, distr, proto);
  159.                 nnfree(&line);
  160.             }
  161.         }
  162.         (void) nfclose(arttext);
  163.     }
  164. }
  165.  
  166. /*
  167.  * Fake up a minimal article struct for msgid using group to.remotesys and
  168.  * distribution distr, then invoke transmit().  If there is a history
  169.  * entry for msgid, supply the list of file names too.
  170.  * Generate a log entry for each message-id transmitted.
  171.  */
  172. static statust
  173. faketrans(msgid, remotesys, distr, proto)
  174. register char *msgid, *remotesys;
  175. char *distr;
  176. int proto;
  177. {
  178.     struct article fakeart;
  179.     register char *ng;
  180.     register char *histent;
  181.     register struct article *fap = &fakeart;
  182.     time_t now;
  183.     statust status = ST_OKAY;
  184.  
  185.     ng = nemalloc((unsigned)(STRLEN("to.") + strlen(remotesys) + 1));
  186.     (void) strcpy(ng, "to.");
  187.     (void) strcat(ng, remotesys);
  188.  
  189.     artinit(fap);
  190.  
  191.     fap->h.h_ngs = ng;
  192.     fap->h.h_distr = (distr != NULL? distr: ng);
  193.     fap->h.h_msgid = msgid;
  194.     fap->h.h_path = hostname();
  195.     fap->a_charswritten = AVEARTSIZE;
  196.     histent = gethistory(msgid);
  197.     if (histent == NULL || (fap->a_files = findfiles(histent)) == NULL)
  198.         fap->a_files = "no.such.article!";
  199.  
  200.     timestamp(stdout, &now);    /* start log line */
  201.     if (printf(" %s %c %s", sendersite(nullify(fap->h.h_path)),
  202.         (proto == PROTO_IHAVE? 'i': 's'), fap->h.h_msgid) == EOF)
  203.         fulldisk(fap, "stdout");
  204.     transmit(fap, "");    /* write on batch file; write sys name on stdout */
  205.     (void) putchar('\n');        /* end log line */
  206.     status |= fap->a_status;    /* pass back failure writing batch file */
  207.  
  208.     fap->h.h_ngs = NULL;
  209.     fap->h.h_distr = NULL;
  210.     fap->h.h_msgid = NULL;
  211.     fap->h.h_path = NULL;
  212.     fap->a_files = NULL;
  213.     artfree(fap);
  214.  
  215.     free(ng);
  216.     return status;
  217. }
  218.